# coding: utf-8

import time
from datetime import datetime, timedelta

import random
from copy import deepcopy

from common.models import model_factory, DemandStatus
from common.schedule.demand_utils import clear_cache
from common.schedule.opc_celery import celery_app
from common.utils import DB


@celery_app.task(name='auto_offer_task')
def auto_offer_task(demand_id, published_count, user_ids, expect_bid_point, last_user_id=None):
    """
    create by ld_wu 2018-02-02
    自动浇水任务
    :return:
    """
    def get_random():
        if expect_bid_point < 50:
            feed = range(1, 3)
        elif expect_bid_point < 100:
            feed = range(1, 5)
        else:
            feed = range(2, 7)

        return random.choice(feed) * 5

    def new_offer():
        model_factory.partic.create(
            session,
            demand_id=demand_id,
            supplier_id=user_id,
            status=10,
            offer=offer,
            offer_at=timestamp,
            demand_status=demand.status,
            published_count=published_count,
            credit=-10000,
            is_robot=True
        )

    def next_task(start=15, end=30):
        """
        created by chenhj at 02/02/2018

        """
        clear_cache(demand_id)
        now = datetime.utcnow()
        delay = random.randint(start, end)
        auto_offer_task.apply_async(
            (demand_id, published_count, user_ids, expect_bid_point, user_id),
            eta=now + timedelta(seconds=delay),
            expires=now + timedelta(seconds=10 + delay)
        )

    with DB() as session:
        timestamp = int(time.time())
        demand = model_factory.demand.get_by_args(session, id=demand_id, status=10)
        # 只有在竞价模式才会浇水
        # 非当前发布次数的项目不进行浇水
        if not demand or demand.published_count != published_count:
            return

        if timestamp - demand.published_at >= 298:
            return

        max_offer_partics_cnt = session.query(model_factory.partic).filter(
            model_factory.partic.demand_id == demand_id,
            model_factory.partic.published_count == published_count,
            model_factory.partic.is_robot.__eq__(False),
            model_factory.partic.offer == 200
        ).count()

        # 每次随机抽取的用户过滤掉上一次出价的用户
        random_user_ids = deepcopy(user_ids)
        if last_user_id and last_user_id in random_user_ids:
            random_user_ids.remove(last_user_id)
        user_id = random.choice(random_user_ids)

        # 最后30秒不出价
        if timestamp - demand.published_at >= 270 and not max_offer_partics_cnt:
            next_task(2, 10)

        print(
            'robot task demand_id:{} user_ids:{} '
            '\nlast_user_id:{} random_user_ids:{}'.format(
                demand_id, user_ids, last_user_id, random_user_ids
            )
        )

        # 只要有工程商爆灯, 则机器人同步爆灯
        if max_offer_partics_cnt >= 1:
            max_bid_len = len(user_ids) - 2
            current_max_bid_len = session.query(model_factory.partic).filter(
                model_factory.partic.demand_id == demand_id,
                model_factory.partic.published_count == published_count,
                model_factory.partic.offer == 200,
                model_factory.partic.is_robot.__eq__(True)
            ).count()
            if current_max_bid_len < max_bid_len:
                self_partic = model_factory.partic.get_by_args(
                    session,
                    demand_id=demand_id,
                    supplier_id=user_id
                )

                offer = 200
                # 该机器人已出价
                if self_partic:
                    if self_partic.offer < offer:
                        self_partic.offer_at = timestamp
                        self_partic.offer = offer
                else:
                    new_offer()
                next_task(1, 10)
                return
            else:
                return

        # 当前最高价
        partic = session.query(model_factory.partic).filter(
            model_factory.partic.demand_id == demand_id,
            model_factory.partic.published_count == published_count,
            model_factory.partic.demand_status.notin_([
                DemandStatus.BRONZE_MEDAL_DISCOUNT.value,
                DemandStatus.DISPATCHING.value,
                DemandStatus.MASTER_DISPATCHING.value
            ])
        ).order_by(
            model_factory.partic.offer.desc()
        ).first()

        if partic:
            # 当前最高价已高于期望价, 则不再出价
            if partic.offer >= expect_bid_point:
                next_task()
                return

            self_partic = model_factory.partic.get_by_args(
                session,
                demand_id=demand_id,
                supplier_id=user_id
            )

            offer = min(get_random() + int(partic.offer), expect_bid_point)
            # 该机器人已出价
            if self_partic:
                self_partic.offer_at = timestamp
                self_partic.offer = offer
            else:
                new_offer()
        else:
            # 期望成交价低于100, 则首次报价出10
            # 否则出 5 * [6, 10]
            if expect_bid_point < 100:
                offer = 10
            else:
                offer = 5 * random.choice(range(6, 11))
            new_offer()

        next_task()
